package com.droidlogic.FileBrower.GiecSmb;

/**
 * Created by arpitkh996 on 16-01-2016.
 */

import android.content.Context;
import android.os.Looper;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import jcifs.netbios.NbtAddress;

public class SubnetScanner extends Thread {
    public static final int RETRY_COUNT = 1;
    private final Object mLock;
    private List<Computer> mResults;
    private ScanObserver observer;
    ExecutorService pool;
    private List<Future<Computer>> tasks;
    public interface ScanObserver {
        void computerFound(Computer computer);

        void searchFinished();
    }

    class Task implements Callable<Computer> {
        String addr;

        public Task(String str) {
            this.addr = str;
        }

        public Computer call() throws Exception {
            LogUtils.d("call "+this.addr);
            try {
                NbtAddress[] allByAddress = NbtAddress.getAllByAddress(this.addr);
                if (allByAddress == null || allByAddress.length <= 0) {
                    return new Computer(null, this.addr);
                }
                return new Computer(allByAddress[0].getHostName(), this.addr);
            } catch (UnknownHostException e) {
                return new Computer(null, this.addr);
            }
        }
    }    

    public SubnetScanner(Context mContext) {
        this.mLock = new Object();
        this.tasks = new ArrayList(260);
        this.pool = Executors.newFixedThreadPool(40);
        this.mResults = new ArrayList();
    }


    public void run() {
    	Looper.prepare();
        String ipStr = Utils.getIPAddress(true);
        LogUtils.d("ipStr="+ipStr);
        if (ipStr.length()>0) {
            String formatIpAddress = ipStr;
            String substring = formatIpAddress.substring(0, formatIpAddress.lastIndexOf('.') + 1);
            if (!isInterrupted()) {
                int ipAddress = 0;
                for (ipAddress = 0; ipAddress < 100; ipAddress++) {
                    if(isInterrupted() || this.pool.isShutdown()) break;
                    if(ipAddress>0)
                        this.tasks.add(this.pool.submit(new Task(substring + ipAddress)));
                    if(isInterrupted() || this.pool.isShutdown()) break;
                    this.tasks.add(this.pool.submit(new Task(substring + (ipAddress + 100))));
                    if(isInterrupted() || this.pool.isShutdown()) break;
                    if (ipAddress < 55) {
                        this.tasks.add(this.pool.submit(new Task(substring + (ipAddress + 200))));
                    }
                }
                while (!this.tasks.isEmpty()) {
                    int size = this.tasks.size();
                    int i = 0;
                    while (i < size) {
                        if (!isInterrupted()) {
                            try {
                                Computer computer = (Computer) ((Future) this.tasks.get(i)).get(1, TimeUnit.MILLISECONDS);
                                this.tasks.remove(i);
                                size--;
                                if (computer.name != null) {
                                    LogUtils.d("SMB host found at "+computer.addr);
                                    onFound(computer);
                                } else {
                                	LogUtils.e("No SMB host found at " + computer.addr);
                                }
                                ipAddress = size;
                            } catch (InterruptedException e) {
                                return;
                            } catch (ExecutionException e2) {
                                Throwable th = e2;
                                ipAddress = size;
                                LogUtils.e(th.toString());
                            } catch (TimeoutException e3) {
                                ipAddress = size;
                            }
                            i++;
                            size = ipAddress;
                        } else {
                            LogUtils.d("task interrupt");
                            return;
                        }
                    }
                }                
            } else {
                return;
            }
        }
        synchronized (this.mLock) {
            if (this.observer != null) {
                this.observer.searchFinished();
            }
        }
        Looper.loop();
        this.pool.shutdown();
    }   

    void onFound(Computer computer) {
        LogUtils.d("onFound "+computer.addr);
        this.mResults.add(computer);
        synchronized (this.mLock) {
            if (this.observer != null) {
                this.observer.computerFound(computer);
            }
        }
    }

    public void setObserver(ScanObserver scanObserver) {
        synchronized (this.mLock) {
            this.observer = scanObserver;
        }
    }

    public void interrupt() {
        LogUtils.d("interrupt");
        super.interrupt();
        try {
            this.pool.shutdownNow();
        } catch (Throwable th) {

        }
    }

    public List<Computer> getResults() {
        return new ArrayList(this.mResults);
    }

}

